#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>
#include <string>
#include <cstdio>
#include <cassert>
#include <cerrno>

int main()
{
    int pipefd[2] = { 0 };
    //创建管道文件
    int n = pipe(pipefd);
    if(n == -1)
    {
        printf("错误码：%d, 错误描述：%s\n", errno, strerror(errno));
        return errno;
    }

    //std::cout << pipefd[0] << " " << pipefd[1] << std::endl;
    
    int id = fork();
    assert(id != -1);

    if(id == 0)
    {
        //子进程写入数据
        //写之前先关闭管道文件的读 pipefd[0]
        close(pipefd[0]);

        std::string str("hello world");
        int cnt = 1;
        char buffer[1024];

        while(true)
        {
            char x = 'X';
            write(pipefd[1], &x, 1);
            std::cout << "count:" << cnt++ << std::endl; //每写入一个字符就计数加一，管道文件存储上限65535
            sleep(1);

            //snprintf(buffer, sizeof buffer, "子进程pid：%d, %s : %d", getpid(), str.c_str(), cnt++);
            //将内容写入到管道中 
            //write(pipefd[1], buffer, strlen(buffer));
            //sleep(10);  //子间歇写，父要等子写了才能读取  

            //if(cnt > 5) break; //写5条就关闭写，查看父进程现象：写功能关闭，父进程直接读到管道文件的结尾
        }

        //写完就关闭
        close(pipefd[1]);
    }

    //父进程读数据,关闭写的功能
    close(pipefd[1]);

    char buffer[1024];
    int cnt = 1;
    //读取管道内容
    while(true)
    {
        //sleep(10); //子进程一直写，父进程间歇读取内容:管道文件也有大小 
        int n = read(pipefd[0], buffer, sizeof(buffer) - 1);
        if(n > 0)
        {
            buffer[n] = '\0';
            std::cout << "我是父进程，" << buffer << std::endl;
        }
        else if(n == 0) //到文件末尾
        {
            std::cout << "读取到文件的末尾" << std::endl;
            break;
        }
        else
        {
            std::cout << "读取文件错误" << std::endl;
            break;
        }
        
        sleep(1);
        if(cnt++ > 5) break; //读5条内容后就关闭读功能，查看现象：子一直写，没有人读，OS直接发送信号中断
    }

    close(pipefd[0]);

    int status = 0;
    waitpid(id, &status, 0);
    //查看父没有读的时候，被OS发送的什么信号中断：SIGPIPE 13号 
    std::cout << "退出信号：" << (status & 0x7f) << std::endl;

    return 0;
}
